package com.zx.system.block.service.impl;

import com.zx.core.context.TenantContextHolder;
import com.zx.core.enums.GenderEnum;
import com.zx.core.enums.StatusEnum;
import com.zx.core.page.PageInfo;
import com.zx.core.wrapper.ObjectWrapper;
import com.zx.core.wrapper.PageWrapper;
import com.zx.core.wrapper.ResponseWrapper;
import com.zx.feign.client.dto.GetSysUserResponseDTO;
import com.zx.security.block.uitls.SecurityUtils;
import com.zx.system.block.dao.*;
import com.zx.system.block.mapstruct.UserMapStructMapper;
import com.zx.system.block.model.*;
import com.zx.system.block.param.UserParam;
import com.zx.system.block.service.ISysDeptService;
import com.zx.system.block.service.ISysUserService;
import com.zx.system.block.utils.SystemNoUtils;
import com.zx.system.block.vo.SysUserVO;
import com.zx.validation.annotation.ParameterValidation;
import com.zx.validation.annotation.ParameterValidations;
import com.zx.validation.enums.ValidateRulesEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * description: 业务层用户服务实现 <br>
 * create: 2024-08-24 11:59
 * </p>
 *
 * @author zhou  xun
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl implements ISysUserService {
    private final SysUserMapper sysUserMapper;
    private final SysRoleMapper sysRoleMapper;
    private final SysUserRoleMapper sysUserRoleMapper;
    private final SysUserPostMapper sysUserPostMapper;
    private final SysPostMapper sysPostMapper;
    private final PasswordEncoder passwordEncoder;
    private final ISysDeptService iSysDeptService;


    /**
     * 根据手机号查询用户信息
     *
     * @param phoneNumber 手机号
     * @return {@link SysUser}
     * @author zhou  xun
     * @since 2024-08-23
     */
    @Override
    public SysUser selectUserByPhoneNumber(String phoneNumber) {
        return sysUserMapper.findByPhoneNumber(phoneNumber, T);
    }

    /**
     * 根据邮箱查询用户信息
     *
     * @param email 邮箱
     * @return {@link SysUser}
     * @author zhou  xun
     * @since 2024-08-23
     */
    @Override
    public SysUser selectUserByEmail(String email) {
        return sysUserMapper.findByEmail(email);
    }

    /**
     * 根据登录凭证查询用户信息
     *
     * @param loginCredential 登录凭证（可以是用户名、手机号或邮箱）
     * @return {@link SysUser}
     * @author zhou  xun
     * @since 2024-08-23
     */
    @Override
    public SysUser selectUserByLoginCredential(String loginCredential) {
        // 判断登录凭证类型
        if (isValidPhoneNumber(loginCredential)) {
            return selectUserByPhoneNumber(loginCredential);
        } else if (isValidEmail(loginCredential)) {
            return selectUserByEmail(loginCredential);
        } else {
            return selectUserByUserName(loginCredential);
        }
    }

    /**
     * 验证是否为有效的手机号
     *
     * @param phoneNumber 手机号
     * @return 是否有效
     */
    private boolean isValidPhoneNumber(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.isEmpty()) {
            return false;
        }
        // 简单的手机号验证（11位数字，以1开头）
        return phoneNumber.matches("^1[3-9]\\d{9}$");
    }

    /**
     * 验证是否为有效的邮箱
     *
     * @param email 邮箱
     * @return 是否有效
     */
    private boolean isValidEmail(String email) {
        if (email == null || email.isEmpty()) {
            return false;
        }
        // 简单的邮箱验证
        return email.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");
    }

    /**
     * 分页查询用户列表
     *
     * @param userParam 用户查询参数
     * @return {@link PageWrapper <SysUser>}
     * @author zhou  xun
     * @since 2024-09-25
     */
    @Override
    public PageWrapper<SysUser> getUserListByPage(UserParam userParam) {
        PageWrapper<SysUser> result = new PageWrapper<>();
        if (userParam.getStatus() != null) {
            StatusEnum enumByCode = StatusEnum.getEnumByCode(userParam.getStatus());
            if (null == enumByCode) {
                result.fail("传入的账号状态错误!");
                return result;
            }
        }
        PageInfo pageInfo = new PageInfo(userParam.getPageNum(), userParam.getPageSize());
        userParam.setPageNum(pageInfo.getPageNum());
        userParam.setPageSize(pageInfo.getPageSize());

        Long count = sysUserMapper.getUserListCount(TenantContextHolder.getTenantId(), userParam.getDeptId(), userParam.getName(), userParam.getEmail(),
                userParam.getPhoneNumber(), userParam.getStatus(), userParam.getCreateTimeStart(), userParam.getCreateTimeEnd());
        if (count > 0) {
            List<SysUser> sysUserList = sysUserMapper.getUserListByPage(TenantContextHolder.getTenantId(), userParam.getDeptId(), userParam.getName(),
                    userParam.getEmail(), userParam.getPhoneNumber(), userParam.getStatus(),
                    userParam.getCreateTimeStart(), userParam.getCreateTimeEnd(),
                    userParam.getPageNum(), userParam.getPageSize());

            result.setData(sysUserList);
        }
        result.setTotal(count);
        result.setCurrentPageNum(userParam.getPageNum());
        result.setTotalPage(pageInfo);

        return result;
    }

    /**
     * 分页查询用户列表
     *
     * @param userParam 用户查询参数
     * @return {@link PageWrapper <SysUser>}
     * @author zhou  xun
     * @since 2024-09-25
     */
    @Override
    public PageWrapper<SysUserVO> getUserVOListByPage(UserParam userParam) {
        PageWrapper<SysUserVO> result = new PageWrapper<>();
        // 获取用户列表
        PageWrapper<SysUser> pageWrapper = getUserListByPage(userParam);

        // 验证请求是否成功或数据是否为空
        if (pageWrapper.verifyFail()) {
            result.fail(pageWrapper.getMsg());
            return result;
        }

        if (pageWrapper.getData() == null || pageWrapper.getData().isEmpty()) {
            result.setTotal(pageWrapper.getTotal());
            result.setCurrentPageNum(pageWrapper.getCurrentPageNum());
            return result;
        }

        // 获取部门信息
        Map<String, SysDept> deptMap = iSysDeptService.getDept();

        // 转换并处理数据
        List<SysUserVO> processedData = pageWrapper.getData().stream()
                .map(item -> {
                    // 使用MapStruct进行基础属性转换和描述性字段设置
                    SysUserVO sysUserVO = UserMapStructMapper.INSTANCE.sysUserToSysUserVO(item);

                    // 设置部门名称
                    String deptId = item.getDeptId();
                    if (deptId != null && !deptId.isEmpty()) {
                        SysDept sysDept = deptMap.get(deptId);
                        if (sysDept != null) {
                            sysUserVO.setDeptName(sysDept.getName());
                        }
                    }

                    return sysUserVO;
                })
                .collect(Collectors.toList());

        result.setData(processedData);
        result.setTotal(pageWrapper.getTotal());
        result.setCurrentPageNum(pageWrapper.getCurrentPageNum());
        return result;
    }

    /**
     * 新增用户
     *
     * @param userParam 用户参数
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @Override
    public ResponseWrapper addUser(UserParam userParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            //性别验证
            Integer sexValue = Integer.valueOf(userParam.getSex());
            GenderEnum genderEnum = GenderEnum.getGenderBySexValue(sexValue);
            if (null == genderEnum) {
                result.fail("传入的性别错误!");
                return result;
            }
            // 验证用户状态
            StatusEnum statusEnum = StatusEnum.getEnumByCode(userParam.getStatus());
            if (null == statusEnum) {
                result.fail("传入的用户状态错误!");
                return result;
            }
            // 同租户手机号唯一验证
            SysUser sysUserByPhoneNumber = sysUserMapper.findByPhoneNumber(userParam.getPhoneNumber(), TenantContextHolder.getTenantId());
            if (sysUserByPhoneNumber != null) {
                result.fail("该手机号已存在!");
                return result;
            }
            // 同租户邮箱唯一验证
            SysUser sysUserByEmail = sysUserMapper.findByEmail(userParam.getEmail(), TenantContextHolder.getTenantId());
            if (sysUserByEmail != null) {
                result.fail("该邮箱已存在!");
                return result;
            }
            SysUser sysUser = UserMapStructMapper.INSTANCE.userParamToSysUser(userParam);
            sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
            // 设置id
            sysUser.setId(SystemNoUtils.generateSystemId());
            // 设置租户ID
            sysUser.setTenantId(TenantContextHolder.getTenantId());
            sysUser.setCreateBy(SecurityUtils.getUserId());
            sysUser.setCreateTime(LocalDateTime.now());
            sysUserMapper.insert(sysUser);
        } catch (Exception e) {
            log.error("新增用户时发生错误", e);
            result.fail("新增用户时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 编辑用户
     *
     * @param userParam 用户参数
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @Override
    public ResponseWrapper editUser(UserParam userParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            //性别验证 注解验证为整数此处可不考虑转换异常
            Integer sexValue = Integer.valueOf(userParam.getSex());
            GenderEnum genderEnum = GenderEnum.getGenderBySexValue(sexValue);
            if (null == genderEnum) {
                result.fail("传入的性别错误!");
                return result;
            }
            List<SysUser> sysUserList = sysUserMapper.selectUserList(SysUser.builder()
                    .name(userParam.getName())
                    .build());
            if (sysUserList != null && !sysUserList.isEmpty()) {
                if (sysUserList.stream().anyMatch(user -> user.getName().equals(userParam.getName()) && !user.getId().equals(userParam.getId()))) {
                    result.fail("已存在相同用户名称!");
                    return result;
                }
            }
            // 验证用户状态
            StatusEnum statusEnum = StatusEnum.getEnumByCode(userParam.getStatus());
            if (null == statusEnum) {
                result.fail("传入的用户状态错误!");
                return result;
            }
            SysUser sysUser = UserMapStructMapper.INSTANCE.userParamToSysUser(userParam);
            if (null != sysUser.getPassword() && !sysUser.getPassword().trim().isEmpty()) {
                sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
            }
            sysUser.setUpdateBy(SecurityUtils.getUserId());
            sysUser.setUpdateTime(LocalDateTime.now());
            sysUserMapper.updateByPrimaryKeySelective(sysUser);
        } catch (Exception e) {
            log.error("编辑用户时发生错误", e);
            result.fail("编辑用户时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 编辑用户状态
     *
     * @param id     用户id
     * @param status 用户状态 0 停用 1 启用
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @Override
    public ResponseWrapper editUserStatus(String id, Integer status) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证用户状态
            StatusEnum statusEnum = StatusEnum.getEnumByCode(status);
            if (null == statusEnum) {
                result.fail("传入的用户状态错误!");
                return result;
            }
            // 验证用户是否存在
            SysUser selectByPrimaryKey = sysUserMapper.selectByPrimaryKey(id);
            if (null == selectByPrimaryKey) {
                result.fail("传入的用户信息不存在!");
                return result;
            }
            SysUser sysUser = new SysUser();
            sysUser.setId(id);
            sysUser.setStatus(status);
            sysUser.setUpdateBy(SecurityUtils.getUserId());
            sysUser.setUpdateTime(LocalDateTime.now());
            sysUserMapper.updateByPrimaryKeySelective(sysUser);
        } catch (Exception e) {
            log.error("编辑用户状态时发生错误", e);
            result.fail("编辑用户状态时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 删除用户
     *
     * @param userId 用户id
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2024-10-29
     */
    @Override
    public ResponseWrapper deleteUser(String userId) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证角色是否存在
            SysUser selectByPrimaryKey = sysUserMapper.selectByPrimaryKey(userId);
            if (null == selectByPrimaryKey) {
                result.fail("传入的角色信息不存在!");
                return result;
            }
            if ("admin".equals(selectByPrimaryKey.getName())) {
                result.fail("超级管理员不能删除!");
                return result;
            }
            sysUserMapper.deleteByPrimaryKey(userId);
        } catch (Exception e) {
            log.error("删除用户时发生错误", e);
            result.fail("删除用户时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 重置密码
     * <p>
     * 注意：该方法不使用参数验证注解，而是在业务逻辑中直接进行参数验证，
     * 因为重置密码场景下需要验证的字段较少且具有特殊性，
     * 直接在业务逻辑中验证比使用统一注解验证更加清晰和高效。
     * </p>
     *
     * @param userParam 用户参数
     * @return {@link ResponseWrapper}
     */
    @Override
    public ResponseWrapper resetUserPwd(UserParam userParam) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            if (null == userParam.getId()) {
                result.fail("重置密码的用户id不能为空!");
                return result;
            }
            if (null == userParam.getPassword()) {
                result.fail("重置的用户密码不能为空!");
                return result;
            }
            SysUser selectByPrimaryKey = sysUserMapper.selectByPrimaryKey(userParam.getId());
            if (null == selectByPrimaryKey) {
                result.fail("重置密码的用户信息不存在!");
                return result;
            }
            SysUser sysUser = new SysUser();
            sysUser.setId(userParam.getId());
            sysUser.setPassword(passwordEncoder.encode(userParam.getPassword()));
            sysUser.setUpdateBy(SecurityUtils.getUserId());
            sysUser.setUpdateTime(LocalDateTime.now());
            sysUserMapper.updateByPrimaryKeySelective(sysUser);
        } catch (Exception e) {
            log.error("重置密码时发生错误", e);
            result.fail("重置密码时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 分配角色
     *
     * @param userId  用户id
     * @param roleIds 角色id列表
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2025-04-13
     */
    @Transactional
    @Override
    @ParameterValidations({
            @ParameterValidation(index = 0, desc = "用户Id", rules = {ValidateRulesEnum.NOT_NULL})
    })
    public ResponseWrapper setUserRole(String userId, String[] roleIds) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证角色是否存在
            List<SysRole> sysRoleList = sysRoleMapper.selectRoleList(null);
            List<String> idlist = sysRoleList.stream().map(SysRole::getId).toList();
            if (!Arrays.asList(roleIds).isEmpty()) {
                for (String roleId : roleIds) {
                    if (!idlist.contains(roleId)) {
                        result.fail("传入的角色信息不存在!");
                        return result;
                    }
                }
                List<SysUserRole> sysUserRoleList = sysUserRoleMapper.selectUserRoleByUserId(userId);
                List<String> checkList = sysUserRoleList.stream().map(SysUserRole::getRoleId).toList();
                List<String> addList = new ArrayList<>();
                List<String> deleteList = new ArrayList<>();
                for (String roleId : roleIds) {
                    if (!checkList.contains(roleId)) {
                        addList.add(roleId);
                    }
                }
                for (String roleId : checkList) {
                    if (!Arrays.asList(roleIds).contains(roleId)) {
                        deleteList.add(roleId);
                    }
                }
                if (!addList.isEmpty()) {
                    List<SysUserRole> sysUserRoleList1 = addList.stream().map(roleId -> new SysUserRole(userId, roleId)).toList();
                    sysUserRoleMapper.batchInsert(sysUserRoleList1);
                }
                if (!deleteList.isEmpty()) {
                    sysUserRoleMapper.batchDeleteByUserAndRoleIds(userId, deleteList);
                }
            } else {
                sysUserRoleMapper.deleteByUserId(userId);
            }
        } catch (Exception e) {
            log.error("分配角色时发生错误", e);
            result.fail("分配角色时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 分配岗位
     *
     * @param userId  用户id
     * @param postIds 岗位id列表
     * @return {@link ResponseWrapper}
     * @author zhou  xun
     * @since 2025-04-13
     */
    @Override
    public ResponseWrapper setUserPost(String userId, String[] postIds) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 验证岗位是否存在
            List<SysPost> sysPostList = sysPostMapper.selectPostList(null, null, null, null, null);
            List<String> idlist = sysPostList.stream().map(SysPost::getId).toList();
            if (!Arrays.asList(postIds).isEmpty()) {
                for (String postId : postIds) {
                    if (!idlist.contains(postId)) {
                        result.fail("传入的岗位信息不存在!");
                        return result;
                    }
                }
                List<SysUserPost> sysUserPostList = sysUserPostMapper.selectUserPostByUserId(userId);
                List<String> checkList = sysUserPostList.stream().map(SysUserPost::getPostId).toList();
                List<String> addList = new ArrayList<>();
                List<String> deleteList = new ArrayList<>();
                for (String postId : postIds) {
                    if (!checkList.contains(postId)) {
                        addList.add(postId);
                    }
                }
                for (String postId : checkList) {
                    if (!Arrays.asList(postIds).contains(postId)) {
                        deleteList.add(postId);
                    }
                }
                if (!addList.isEmpty()) {
                    List<SysUserPost> sysUserPostList1 = addList.stream().map(postId -> new SysUserPost(userId, postId)).toList();
                    sysUserPostMapper.batchInsert(sysUserPostList1);
                }
                if (!deleteList.isEmpty()) {
                    sysUserPostMapper.batchDeleteByUserAndPostIds(userId, deleteList);
                }
            } else {
                sysUserPostMapper.deleteByUserId(userId);
            }
        } catch (Exception e) {
            log.error("分配岗位时发生错误", e);
            result.fail("分配岗位时发生错误: " + e.getMessage());
        }
        return result;
    }

    /**
     * 查询用户的角色id列表
     *
     * @param userId 用户id
     * @return {@link  ObjectWrapper } 菜单id集合
     * @author zhou  xun
     * @since 2025-04-15
     */
    @Override
    public ObjectWrapper<Set<String>> selectRoleIdsByUserId(String userId) {
        ObjectWrapper<Set<String>> result = new ObjectWrapper<>();
        List<SysRole> sysRoleList = sysRoleMapper.selectRoleByUserId(userId);
        if (null != sysRoleList && !sysRoleList.isEmpty()) {
            Set<String> roleIdSet = sysRoleList.stream()
                    .filter(sysRole -> StatusEnum.ENABLE.getCode().equals(sysRole.getStatus()))
                    .map(SysRole::getId)
                    .collect(Collectors.toSet());
            if (!roleIdSet.isEmpty()) {
                result.setData(roleIdSet);
            }
        }
        return result;
    }

    /**
     * 查询用户信息
     *
     * @param userId 用户id
     * @return {@link ObjectWrapper} 用户信息
     */
    @Override
    public ObjectWrapper<GetSysUserResponseDTO> getUserById(String userId) {
        ObjectWrapper<GetSysUserResponseDTO> result = new ObjectWrapper<>();
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(userId);
        if (null != sysUser) {
            GetSysUserResponseDTO getSysUserResponseDTO = UserMapStructMapper.INSTANCE.sysUserToSysUserDTO(sysUser);
            result.setData(getSysUserResponseDTO);
        }
        return result;
    }

    /**
     * 修改用户密码
     *
     * @param userId      用户ID
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     * @return {@link ResponseWrapper}
     */
    @Override
    public ResponseWrapper changePassword(String userId, String oldPassword, String newPassword) {
        ResponseWrapper result = new ResponseWrapper();
        try {
            // 查询用户信息
            SysUser user = sysUserMapper.selectByPrimaryKey(userId);
            if (user == null) {
                result.fail("用户不存在");
                return result;
            }

            // 验证旧密码是否正确
            if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
                result.fail("旧密码错误");
                return result;
            }

            // 验证新旧密码是否相同
            if (passwordEncoder.matches(newPassword, user.getPassword())) {
                result.fail("新密码不能与旧密码相同");
                return result;
            }

            // 验证新密码强度
            if (!newPassword.matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{6,20}$")) {
                result.fail("密码必须包含大小写字母和数字，长度在6-20个字符之间");
                return result;
            }

            // 更新密码
            SysUser updateUser = new SysUser();
            updateUser.setId(userId);
            updateUser.setPassword(passwordEncoder.encode(newPassword));
            updateUser.setUpdateBy(userId);
            updateUser.setUpdateTime(LocalDateTime.now());
            sysUserMapper.updateByPrimaryKeySelective(updateUser);

            log.info("用户 {} 修改密码成功", userId);
        } catch (Exception e) {
            log.error("修改密码时发生错误", e);
            result.fail("修改密码失败: " + e.getMessage());
        }
        return result;
    }

    /**
     * 根据用户id查询用户信息
     *
     * @param userId 用户id
     * @return {@link SysUser} 用户信息
     * @author zhou  xun
     * @since 2025-04-15
     */
    @Override
    public SysUser selectUserById(String userId) {
        return sysUserMapper.selectByPrimaryKey(userId);
    }
}
